package com.xg.te.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.xg.te.core.bean.WebsiteBean;
import com.xg.te.core.bean.ConstantBean;
import com.xg.te.core.bean.EngineBean;
import com.xg.te.core.bean.IncludeBean;
import com.xg.te.core.bean.PageBean;
import com.xg.te.core.bean.PageReference;
import com.xg.te.plugin.bean.PluginBean;
import com.xg.te.plugin.bean.PluginReference;
import com.xg.te.strategy.bean.StrategyBean;
import com.xg.te.strategy.bean.StrategyReference;

/**
 * 工具类
 * 
 * @author liuguojun
 * @date 2014-06-28
 */
public class XmlUtils {

	private static final Logger logger = Logger.getLogger(XmlUtils.class);
	
	public static XmlUtils getInstance(){
		return new XmlUtils();
	}
	
	/**
	 * 解析XML文件
	 * 
	 * @param file
	 * @return EngineBean
	 */
	public EngineBean parseXml(File file) {
		EngineBean engine = new EngineBean();
		
		Element root = getRoot(file);
		
		engine.setWebsites(parseWebsite(root));
		engine.setIncludes(parseInclude(root));
		engine.setPages(parsePage(root));
		engine.setPlugins(parsePlugin(root));
		engine.setStrategies(parseStrategy(root));
		
		return engine;
	}
	
	/**
	 * 解析agent
	 * 
	 * @param root
	 * @return List<AgentBean>
	 */
	private List<WebsiteBean> parseWebsite(Element root){
		List<WebsiteBean> reList = new LinkedList<WebsiteBean>();
		
		Element aNode = root.element("websites");
		if(aNode == null){
			return null;
		}
		
		List<Element> pList = aNode.elements("website");
		for (Element element : pList) {
			
			Element cNode = element.element("constants");
			List<ConstantBean> constants = new LinkedList<ConstantBean>();
			if (cNode != null){
				List<Element> cList = cNode.elements("constant");
				for (Element child : cList) {
					ConstantBean cons = new ConstantBean();
					cons.setName(child.attributeValue("name"));
					cons.setValue(child.attributeValue("value"));
					
					constants.add(cons);
				}
			}
			
			Element pNode = element.element("pages");
			List<PageReference> pages = new LinkedList<PageReference>();
			if (pNode != null){
				List<Element> cList = pNode.elements("page-ref");
				for (Element child : cList) {
					PageReference page = new PageReference();
					page.setCode(child.attributeValue("code"));
					page.setDesc(child.attributeValue("desc"));
					
					pages.add(page);
				}
			}
	
			WebsiteBean agent = new WebsiteBean();
			agent.setPages(pages);
			agent.setConstants(constants);
			
			reList.add(agent);
		}
		
		return reList;
	}
	
	/**
	 * 解析page
	 * 
	 * @param root
	 * @return List<PageBean>
	 */
	private List<PageBean> parsePage(Element root){
		List<PageBean> reList = new LinkedList<PageBean>();
		
		Element includes = root.element("pages");
		if(includes == null){
			return null;
		}
		
		List<Element> sList = includes.elements("page");
		for (Element element : sList) {
			String code = element.attributeValue("code");
			String name = element.attributeValue("name");
			String desc = element.attributeValue("desc");
			String tpath = element.attributeValue("tpath");
			String hpath = element.attributeValue("hpath");
			
			Element sNode = element.element("strategies");
			List<StrategyReference> strategies = new LinkedList<StrategyReference>();
			if (sNode != null){
				List<Element> cList = sNode.elements("strategy-ref");
				for (Element child : cList) {
					StrategyReference ref = new StrategyReference();
					ref.setCode(child.attributeValue("code"));
					ref.setDesc(child.attributeValue("desc"));
					
					strategies.add(ref);
				}
			}
			
			Element pNode = element.element("plugins");
			List<PluginReference> plugins = new LinkedList<PluginReference>();
			if (pNode != null){
				List<Element> cList = pNode.elements("plugin-ref");
				for (Element child : cList) {
					PluginReference ref = new PluginReference();
					ref.setCode(child.attributeValue("code"));
					ref.setName(child.attributeValue("name"));
					ref.setDesc(child.attributeValue("desc"));
					
					plugins.add(ref);
				}
			}
	
			PageBean page = new PageBean();
			page.setCode(code);
			page.setName(name);
			page.setDesc(desc);
			page.setTpath(tpath);
			page.setHpath(hpath);
			page.setPlugins(plugins);
			page.setStrategies(strategies);
			
			reList.add(page);
		}
		
		return reList;
	}
	
	/**
	 * 解析strategy
	 * 
	 * @param root
	 * @return List<PluginBean>
	 */
	private List<PluginBean> parsePlugin(Element root){
		List<PluginBean> reList = new LinkedList<PluginBean>();
		
		Element pNode = root.element("plugins");
		if(pNode == null){
			return null;
		}
		
		List<Element> sList = pNode.elements("plugin");
		for (Element element : sList) {
			String code = element.attributeValue("code");
			String bean = element.attributeValue("bean");
			String init = element.attributeValue("init");
			String desc = element.attributeValue("desc");
			
			String args = null;
			Element sNode = element.element("args");
			if (sNode == null){
				args = "";
			} else {
				args = sNode.getText();
			}
	
			PluginBean plugin = new PluginBean();
			plugin.setCode(code);
			plugin.setBean(bean);
			plugin.setInit(init);
			plugin.setDesc(desc);
			plugin.setArgs(args);
			
			reList.add(plugin);
		}
		
		return reList;
	}
	
	/**
	 * 解析strategy
	 * 
	 * @param root
	 * @return List<StrategyBean>
	 */
	private List<StrategyBean> parseStrategy(Element root){
		List<StrategyBean> reList = new LinkedList<StrategyBean>();
		
		Element sNode = root.element("strategies");
		if(sNode == null){
			return null;
		}
		
		List<Element> sList = sNode.elements("strategy");
		for (Element element : sList) {
			String code = element.attributeValue("code");
			String bean = element.attributeValue("bean");
			String init = element.attributeValue("init");
			String desc = element.attributeValue("desc");
			
			String args = null;
			Element aNode = element.element("args");
			if (aNode == null){
				args = "";
			} else {
				args = aNode.getText();
			}
	
			StrategyBean strategy = new StrategyBean();
			strategy.setCode(code);
			strategy.setBean(bean);
			strategy.setInit(init);
			strategy.setDesc(desc);
			strategy.setArgs(args);
			
			reList.add(strategy);
		}
		
		return reList;
	}
	
	/**
	 * 解析include
	 * 
	 * @param root
	 * @return List<IncludeBean>
	 */
	private List<IncludeBean> parseInclude(Element root){
		List<IncludeBean> reList = new LinkedList<IncludeBean>();
		
		Element iNode = root.element("includes");
		if(iNode == null){
			return null;
		}
		
		List<Element> sList = iNode.elements("include");
		for (Element element : sList) {
			String file = element.attributeValue("file");
	
			IncludeBean include = new IncludeBean();
			include.setFile(file);
			
			reList.add(include);
		}
		
		return reList;
	}

	/**
	 * 获取根节点
	 * 
	 * @param file
	 * @return
	 */
	private Element getRoot(File file) {
		Element root = null;
		
		InputStream is = null;
		try {
			is = new FileInputStream(file);
			SAXReader reader = new SAXReader();
			reader.setValidation(false);
			Document document = reader.read(is);
			
			root = document.getRootElement();
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException ex) {
					logger.error(ex.getMessage(), ex);
				}
			}
		}

		return root;
	}
}
